import traceback

from api.market import *
from api.position import *
from api.trade import *
from utils.commons import sleep_until_run_time
from config import *
import warnings
from utils.dingding import *

warnings.filterwarnings('ignore')


def main():
    # =判断是否单向持仓，若不是程序退出
    if_oneway_mode()

    # 缓存交易币对精度信息
    fetch_symbol_config_precision_info()

    candle_num = 1000  # 每次获取的K线数量
    # ===获取对应币对历史数据，删除最新一行数据
    symbol_candle_data = bn_fetch_candle_data(candle_num)

    while True:
        # ===获取持仓数据===
        # 在每次循环开始时都初始化account_info
        account_info_columns = ['账户权益', '分配比例', '分配资金', '持仓方向', '持仓量', '持仓收益', '持仓均价']
        account_info = pd.DataFrame(index=symbol_config.keys(), columns=account_info_columns)  # 转化为dataframe

        # 更新持仓信息account_info
        account_info = bn_fetch_future_position(account_info)
        print('当前持仓信息:\n', account_info, '\n')

        # ===获取U本位合约账户净值(不包含未实现盈亏)
        equity = get_position_equity()

        # ===提前报送资金费率信息并发送钉钉
        calcutate_funding_rate(account_info)

        # ===将账户净值和账户信息发送钉钉
        send_dingding_msg_for_position(equity, account_info)

        # ===获取策略执行时间，并sleep至该时间===
        run_time = sleep_until_run_time('1h')

        # ===并行获取所有币种最近数据===
        exchange.timeout = 1000  # 即将获取最新数据，临时将timeout设置为1s，加快获取数据速度
        candle_num = 5  # 需要获取的最新K线数量。理论上只需要2根，冗余

        # 获取数据
        symbol_lasted_candle_data = single_threading_get_bn_candle_data(account_info, run_time, candle_num)
        print('\n当前持仓信息:\n', account_info, '\n')

        # for symbol in symbol_config:
        #     print('symbol_candle_data', symbol_candle_data[symbol], '\n')
        #     print('symbol_lasted_candle_data', symbol_lasted_candle_data[symbol], '\n')

        # 将symbol_candle_data和最新获取的recent_candle_data数据合并
        symbol_candle_data = merge_symbol_candle_data(symbol_candle_data, symbol_lasted_candle_data)

        # 拼接后币对的历史数据为
        for symbol in symbol_candle_data:
            print(f'合并后，{symbol}的k线数据为\n', symbol_candle_data[symbol].tail(3), '\n')

        # =计算每个币种的交易信号
        symbol_signal = calculate_signal(account_info, symbol_candle_data)

        # account_info_path = './data/account_info.csv'
        # account_info.to_csv(account_info_path, sep=',', index=True, header=True)
        print(f'\n当前周期的account_info信息为：\n{account_info}\n')
        print('本周期交易计划:', symbol_signal)

        # ==========下单==========
        exchange.timeout = exchange_timeout  # 下单时需要增加timeout的时间，将timout恢复正常
        # 计算下单信息
        symbol_order_params = cal_all_order_info(symbol_signal, account_info)
        if symbol_order_params:
            print('\n订单参数为：\n', pd.DataFrame(symbol_order_params))

        # ===开始批量下单
        place_binance_batch_order(symbol_order_params)

        # 本次循环结束
        print('\n', '-' * 40, '本次循环结束，%d秒后进入下一次循环' % long_sleep_time, '-' * 40, '\n\n')
        time.sleep(long_sleep_time)


if __name__ == '__main__':
    send_dingding_msg('\n择时策略实盘程序运行情况：\n')
    # ===设置页面最大杠杆
    reset_leverage(5)
    while True:
        try:
            main()
        except Exception as e:
            msg = '系统出错，10s之后重新运行，出错原因: ' + str(e)
            print(msg)
            print(traceback.format_exc())
            send_dingding_msg(msg)
            time.sleep(long_sleep_time)
